﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;

using Microsoft.SharePoint.Administration;
using System.Security.Permissions;

namespace SPBusiness
{
   /// <summary>
   /// Writes entries to ULS Log Service
   /// Inherits the SPDiagnosticsServiceBase for custom ULS Logging Service
   /// The SharePoint API doesn’t provide any method which would allow you to provide the name of the product that logged the message.
   /// </summary>
   public sealed class Logging
   {
             /// <summary>
      /// Logging class has only Static Methods, no constructor needed.
       /// </summary>
      private Logging() { }

      /// <summary>
      /// This method writes and entry on ULS by instantiating a derived class of SPDiagnosticsServiceBase.
      /// MOCAF: would warn because it can not go deeper in this method.
      /// </summary>
      /// <param name="pNameSpace">Namespace of the assembly</param>
      /// <param name="pClass">Class name throwing the exception</param>
      /// <param name="pMethod">Method name throwing the exception</param>
      /// <param name="pException">Exception object</param>
      public static void LogMessase(string pNameSpace, string pClass, string pMethod, Exception pException)
      {
         ULSCustomLogService vULSCustomLogService = new ULSCustomLogService();

         vULSCustomLogService.WriteException(pNameSpace, pClass, pMethod, pException);
      }

      /// <summary>
      /// This method writes and entry on ULS by instantiating a derived class of SPDiagnosticsServiceBase.
      /// MOCAF: would warn because it can not go deeper in this method.
      /// </summary>
      /// <param name="pNameSpace">Namespace of the assembly</param>
      /// <param name="pClass">Class name</param>
      /// <param name="pMethod">Method name</param>
      /// <param name="pMessage">Message</param>
      public static void LogMessase(string pNameSpace, string pClass, string pMethod, string pMessage)
      {
         ULSCustomLogService vULSCustomLogService = new ULSCustomLogService();
         vULSCustomLogService.WriteMessage(pNameSpace, pClass, pMethod, pMessage, TraceSeverity.Unexpected, EventSeverity.ErrorCritical);

      }

      /// <summary>
      /// This method writes and entry on ULS by instantiating a derived class of SPDiagnosticsServiceBase.
      /// MOCAF: would warn because it can not go deeper in this method.
      /// </summary>
      /// <param name="pNameSpace">Namespace of the assembly</param>
      /// <param name="pClass">Class name</param>
      /// <param name="pMethod">Method name</param>
      /// <param name="pMessage">Message</param>
      public static void LogMessase(string pNameSpace, string pClass, string pMethod, string pMessage, EventSeverity pEventSeverity)
      {
         ULSCustomLogService vULSCustomLogService = new ULSCustomLogService();
         vULSCustomLogService.WriteMessage(pNameSpace, pClass, pMethod, pMessage, TraceSeverity.Monitorable, pEventSeverity);

      }
   }


   /// <summary>
   /// Inherits the SPDiagnosticsServiceBase for custom ULS Logging Service
   /// The SharePoint API doesn’t provide any method which would allow you to provide the name of the product that logged the message.
   /// </summary>
   public class ULSCustomLogService : SPDiagnosticsServiceBase
   {
      public string LogProduct { get; set; }
      public string LogCategory { get; set; }
      public TraceSeverity LogTraceSeverity { get; set; }
      public EventSeverity LogEventSeverity { get; set; }      

      /// <summary>
      /// 
      /// </summary>
      public ULSCustomLogService() : base("Custom ULS Logging Service", SPFarm.Local) { }

      /// <summary>
      /// 
      /// </summary>
      /// <returns></returns>
      [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
      protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
      {
         List<SPDiagnosticsArea> vSPDiagnosticsAreaList = new List<SPDiagnosticsArea>{
              new SPDiagnosticsArea(LogProduct, new List<SPDiagnosticsCategory>{
                 new SPDiagnosticsCategory(LogCategory, LogTraceSeverity, LogEventSeverity)
              })
              };
         return vSPDiagnosticsAreaList;
      }

      /// <summary>
      /// 
      /// </summary>
      /// <param name="productName"></param>
      /// <param name="categoryName"></param>
      /// <param name="methodName"></param>
      /// <param name="pException"></param>
      public void WriteException(string productName, string categoryName, string methodName, Exception pException)
      {
         LogProduct = productName;
         LogCategory = categoryName;
         LogTraceSeverity = TraceSeverity.Unexpected;
         LogEventSeverity = EventSeverity.ErrorCritical;
         SPDiagnosticsCategory vSPDiagnosticsCategory = Areas[productName].Categories[categoryName];
         StringBuilder vStringBuilder = new StringBuilder();
         vStringBuilder.Append(methodName + "::" + pException.Message);

         if (pException.StackTrace != null)
         {
            vStringBuilder.AppendLine(pException.StackTrace);
         }
         if (pException.InnerException != null)
         {
            vStringBuilder.AppendLine(pException.Message);

            if (pException.InnerException.StackTrace != null)
            {
               vStringBuilder.AppendLine(pException.InnerException.StackTrace);
            }
         }
         WriteTrace(0, vSPDiagnosticsCategory, TraceSeverity.Unexpected, vStringBuilder.ToString());
      }

      /// <summary>
      /// 
      /// </summary>
      /// <param name="productName"></param>
      /// <param name="categoryName"></param>
      /// <param name="methodName"></param>
      /// <param name="pMessage"></param>
      /// <param name="vTraceSeverity"></param>
      public void WriteMessage(string productName, string categoryName, string methodName, string pMessage, TraceSeverity pTraceSeverity, EventSeverity pEventSeverity)
      {
         LogProduct = productName;
         LogCategory = categoryName;
         LogTraceSeverity = pTraceSeverity;
         LogEventSeverity = pEventSeverity;
         SPDiagnosticsCategory vSPDiagnosticsCategory = Areas[productName].Categories[categoryName];
         StringBuilder vStringBuilder = new StringBuilder();
         vStringBuilder.Append(methodName + "::" + pMessage);
         WriteTrace(0, vSPDiagnosticsCategory, pTraceSeverity, vStringBuilder.ToString());
      }

   }


}
